package agent

import (
	"context"
	corev1 "gluenet/internal/agent/api/core/v1"
	"gluenet/internal/agent/depend"
	"gluenet/internal/agent/driver/rpcdriver"
	"gluenet/internal/agent/server"
	"gluenet/internal/agent/server/httpserver"
	"gluenet/internal/agent/server/rpcserver"
	"time"

	"golang.org/x/sync/errgroup"
)

func init() {
	depend.Provide(NewAgentServer)
}

type AgentServer struct {
	servers []server.Server
}

// 构建agent的 http/rpc 服务
func NewAgentServer(cfg *corev1.Agent) (agent *AgentServer, err error) {
	var servers []server.Server

	serverFactories := []server.ServerFactory{
		httpserver.InitServer,
		rpcserver.InitServer,
	}

	for _, factory := range serverFactories {

		if s, err := factory(cfg); err != nil {
			return nil, err
		} else if s != nil {
			servers = append(servers, s)
		}

	}

	return &AgentServer{
		servers: servers,
	}, nil
}

func (a *AgentServer) Init() {
	for _, server := range a.servers {
		s := server
		go s.ListenAndServe()
	}
}

func (a *AgentServer) Close() error {
	var eg errgroup.Group
	cfg := depend.Produce[*corev1.Agent]()

	logger.Debug("start to close server...")
	for _, server := range a.servers {
		s := server
		eg.Go(func() error {
			ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
			defer cancel()
			return s.Shutdown(ctx)
		})
	}

	eg.Go(func() error {
		logger.Debug("start to log out: ", cfg.Guid)
		return depend.Produce[rpcdriver.RpcDriver]().UnRegister(cfg.Guid)
	})

	return eg.Wait()
}

// func (a *AgentServer) Reload(cfg *corev1.Agent) (agent *AgentServer, err error) {
// 	if err = a.Close(); err != nil {
// 		return
// 	}

// 	if agent, err = NewAgentServer(cfg); err != nil {
// 		return
// 	}

// 	agent.Init()
// 	return
// }
